using DataAnalyticsTools.Core;
using DataAnalyticsTools.Core.AnomalyPointDetect;
using DataAnalyticsTools.Models;
using GrapeCity.Forguncy.Commands;
using GrapeCity.Forguncy.Log;
using GrapeCity.Forguncy.Plugin;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;

namespace DataAnalyticsTools
{
    [Icon("pack://application:,,,/DataAnalyticsTools;component/Resources/Icon.png")]
    [Designer("DataAnalyticsTools.Designer.DataAnalyticsToolsServerCommandDesigner, DataAnalyticsTools")]
    [Category("数据分析")]
    [OrderWeight(500)]
    public class AnomalyDetectionByZSore : Command, ICommandExecutableInServerSideAsync, IServerCommandParamGenerator
    {
        [FormulaProperty]
        [DisplayName("时间序列数据（单变量）")]
        [Description("float[]数组，每个样本的值。")]
        public object featuresExpr { get; set; }


        [FormulaProperty]
        [DisplayName("阈值")]
        [Description("Z-score阈值，默认2.5，超过此值被认为是异常")]
        public object thresholdExpr { get; set; } = 2.5;

        [ResultToProperty]
        [DisplayName("保存异常点到变量")]
        [Description("每个异常点的索引为Index属性，评分为Score属性，异常类型为AnomalyTypeLabel属性")]
        public string ResultTo { get; set; } = "检测到的异常点";


        [ResultToProperty]
        [DisplayName("保存原始结果到变量")]
        public string ResultTo2 { get; set; } = "原始结果";

        public async Task<ExecuteResult> ExecuteAsync(IServerCommandExecuteContext dataContext)
        {
            var features = GeneralConvertors.ConvertToFloatArray(await dataContext.EvaluateFormulaAsync(featuresExpr));
            var threshold = float.Parse((await dataContext.EvaluateFormulaAsync(thresholdExpr))?.ToString() ?? "2.5");

            // 执行计算
            var result = ZScoreDetector.Detect(features, threshold);

            dataContext.Parameters[ResultTo] = result.AnomalyPoints;
            dataContext.Parameters[ResultTo2] = result;

            return new ExecuteResult();
        }

        public override string ToString()
        {
            if (featuresExpr == null)
            {
                return "异常点检测（Z-Score法）";
            }
            else
            {
                return "异常点检测（Z-Score法）：" + ResultTo;
            }
        }

        public override CommandScope GetCommandScope()
        {
            return CommandScope.ExecutableInServer;
        }

        public IEnumerable<GenerateParam> GetGenerateParams()
        {
            List<GenerateParam> result = [];

            result.Add(new GenerateListParam()
            {
                ParamName = this.ResultTo,
                Description = "检测到的异常点",
                ParamScope = CommandScope.All,
                ItemProperties = new List<string>() {
                    "Index",
                    "Value",
                    "Score",
                    "Type",
                    "Deviation",
                    "Reason",
                    "AnomalyTypeLabel",
                    "SeverityLevel"
                }
            });

            result.Add(new GenerateObjectParam()
            {
                ParamName = this.ResultTo2,
                Description = "异常点检测的原始结果",
                ParamScope = CommandScope.All,
                SubPropertiesDescription = new Dictionary<string, string>() {
                    { "Method","检测方法"},
                    { "Threshold","检测阈值"},
                    { "AnomalyScores","各元素的异常分数"},
                    { "Severity","总体的异常严重程度"},
                    { "Confidence","总体的置信度"},
                    { "BaselineValues","基准值"},
                    { "UpperBounds","正常值的上限"},
                    { "LowerBounds","正常值的下限"},
                    { "AnomalyPoints", "检测到的异常点" }
            }
            });

            return result;
        }
    }
}
